﻿using System;
using System.ComponentModel;
using System.Data.SqlClient;
using System.Security.Principal;
using System.Web;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using NLog;

namespace MT.Common.Log {
    public enum ErrorLocation : byte {
        WebApi = 0,
        Client = 1,
        WebSite = 2,
        Storage = 3

    }
    public enum ErrorCode : Int32 {
        [Description ("内部错误")]
        InternalError = 100000, [Description ("无效参数")]
        InvalidParameter = 10001, [Description ("没有权限")]
        NoPermission = 100001, [Description ("api没有请求权限")]
        ApiNoPermissionRequest = 100002, [Description ("验证码错误")]
        VerificationCodeError = 100003, [Description ("手机号码已注册")]
        PhoneNumberHasRegistered = 100004, [Description ("唯一标识已存在")]
        UniqueIDNotExist = 100005, [Description ("身份证号码长度错误")]
        CardIdLengthError = 100006, [Description ("证件号码长度错误")]
        IdentificationNumberError = 100007, [Description ("未选择数据")]
        NotSelectData = 100008, [Description ("XSS 错误")]
        XssError = 100009, [Description ("证件号码已存在")]
        CardIdNotExist = 100010, [Description ("支付失败")]
        PayError = 100011, [Description ("位置信息错误")]
        LocationInfoError = 100012, [Description ("位置不在范围内")]
        LocationNotInScope = 100013, [Description ("用户不存在")]
        UserNotExist = 200001, [Description ("用户过期")]
        UserExpired = 200002, [Description (" 用户名已注册")]
        UserNameHasRegistered = 200003, [Description ("用户未激活")]
        UserNotActive = 200004, [Description ("商品信息错误")]
        GoodsInfoError = 200005, [Description ("用户不存在钉钉id")]
        UserNotDingdingUserExist = 200006,

        [Description ("用户不存在钉钉id,审批流程结束")]
        UserNotDingdingUserExistEndApprovalProcess = 200007, [Description ("公司不存在")]
        CompanyNotExist = 200101,

        [Description ("客户类型不存在")]
        CustomerTypeNotExist = 200201,

        [Description ("字典已存在")]
        DictionaryExist = 200301, [Description ("字典不存在")]
        DictionaryNotExist = 200302, [Description ("字典存在子节点")]
        DictionaryExistChild = 200303, [Description ("字典代码已存在")]
        DictionaryKeyHasExist = 200304,

        [Description ("地区不存在")]
        AreaNotExist = 200401, [Description ("地区已存在")]
        AreaHasExist = 200402, [Description ("地区存在子节点")]
        AreaExistChild = 200403,

        StoreLevelNameIsNull = 200451,
        StoreLevelNotExist = 200452, [Description ("门店不存在")]
        StoreNotExist = 200453, [Description ("门店已存在")]
        StoreHasExist = 200454, [Description ("门店等级已存在")]
        StoreLevelHasExist = 200455,

        [Description ("一个机构只能对一个门店")]
        SingleStoreCorrespondingSingleInstitution = 200456, [Description ("机构不存在")]
        InstitutionNotExist = 200501,
        InstitutionNameIsNull = 200502, [Description ("该机构下有子机构,请先禁用子机构")]
        InstitutionExistChild = 200503, [Description ("机构未选择")]
        InstitutionNotSelected = 200504, [Description ("机构已经存在")]
        InstitutionHasExist = 200505,

        [Description ("机构包含用户")]
        InstitutionContainUser = 200506, [Description ("请先启该机构的子机构")]
        InstitutionChildNotEnable = 200507, [Description ("项目不存在")]
        ProjectNotExist = 200521, [Description ("项目已存在")]
        ProjectHasExist = 200522,

        [Description ("项目包含商品")]
        ProjectContainGoods = 200523, [Description ("菜单不存在")]
        MenuNotExist = 200601, [Description ("菜单已存在")]
        MenuHasExist = 200602, [Description ("页面权限不存在")]
        PermissionNotExist = 200603,

        [Description ("角色不存在")]
        RoleNotExist = 200604,

        [Description ("角色已经存在")]
        RoleHasExist = 200605,

        [Description ("权限不能为空")]
        RoleNotNull = 200606, [Description ("菜单包含子菜单")]
        MenuContainChilds = 200607, [Description ("页面权限已存在")]
        PermissionHasExist = 200608,

        [Description ("页面权限重复")]
        PermissionRepeat = 200607, [Description ("商品菜单分类不存在")]
        GoodsCategoryNotExist = 300001, [Description ("商品菜单分类中包含商品")]
        GoodsCategoryContainGoods = 300002, [Description ("商品菜单分类已存在")]
        GoodsCategoryHasExist = 300003, [Description ("商品菜单分类中包含子分类")]
        GoodsCategoryContainChilds = 300004, [Description ("商品不存在")]
        GoodsNotExist = 300021, [Description ("商品名称已存在")]
        GoodsNameHasExist = 300022, [Description ("商品自定义编码已存在")]
        GoodsCustomCodeHasExist = 300023, [Description ("商品建议价格不能大于最大价格")]
        GoodsNotGreaterThanMaximumPrice = 300024,

        [Description ("商品建议价格不能小于最低价格")]
        GoodsNotLessThanMinimumPrice = 300025,

        [Description ("请选择组合商品")]
        NotSelectGoodsCombination = 300026,

        [Description ("商品价格错误")]
        StoreGoodsPriceError = 300027, [Description ("店铺销售策略不能重复")]
        StoreSalesStrategyByDiscountNotRepeatable = 300029, [Description ("店铺商品分组已存在")]
        StoreGoodsGroupHasExist = 300030, [Description ("店铺商品分组中包含商品")]
        StoreGoodsGroupContainGoods = 300031, [Description ("店铺商品分组不存在")]
        StoreGoodsGroupNotExist = 300032, [Description ("请选择店铺商品分组")]
        StoreGoodsGroupNotSelect = 300033,

        [Description ("店铺商品分组中包含子节点")]
        StoreGoodsGroupContainChilds = 300034, [Description ("店铺商品不存在")]
        StoreGoodsNotExist = 300035, [Description ("店铺商品已存在")]
        StoreGoodsHasExist = 300036, [Description ("店铺商品请选择铺货类型")]
        StoreGoodsNotSelectDistributionType = 300037, [Description ("店铺商品已上架")]
        StoreGoodsHasUpperShelf = 300038,

        [Description ("订单已使用")]
        StoreOrderUsed = 300050, [Description ("店铺订单不存在")]
        StoreOrderNotExist = 300051,

        [Description ("支付金额不能大于订单金额")]
        PayPriceNotGreaterThanOrderPrice = 300052,

        [Description ("总支付金额不能大于订单金额")]
        TotalPayPriceNotGreaterThanOrderPrice = 300053,

        [Description ("店铺订单状态不支持退款")]
        StoreOrderStateDoNotSupportRefund = 300054,

        [Description ("店铺退款记录不存在")]
        StoreRefundRecordNotExist = 300055, [Description ("咨询师已确认")]
        CounselorHasConfirm = 300056, [Description ("审批状态错误")]
        ProcessinstanceHavePassed = 300057,

        [Description ("店铺订单交易成功")]
        StoreOrderSuccessfulTrade = 300058,

        [Description ("店铺订单交易中")]
        StoreOrderInTransaction = 300059, [Description ("预约不存在")]
        MedicalAppointmentNotExist = 400001,

        [Description ("挂号不存在")]
        MedicalRegisterNotExist = 400002, [Description ("质询不存在")]
        MedicalConsultNotExist = 400003, [Description ("划价不存在")]
        MedicalChargeNotExist = 400004, [Description ("回访不存在")]
        MedicalReturnPlanNotExist = 400005, [Description ("划价商品不存在")]
        MedicalChargeGoodsNotExist = 400006, [Description ("商品消费数量不足")]
        MedicalConsumeNumberError = 400010,

        [Description ("客户信息不存在")]
        CustomerInfoNotExist = 400101,

        [Description ("会员号已用完")]
        MembershipNoHasRunOut = 4001002
    }

    //public class ErrorMsg
    //{
    //    private ErrorCode code { get; set; }
    //    public ErrorCode Code
    //    {
    //        get
    //        {
    //            return code;
    //        }

    //        set
    //        {
    //            code = value;
    //            Msg = value.ToString();
    //        }
    //    }

    //    public string Msg { get; set; }

    //    public string Additional { get; set; }
    //}

    //public static class ExceptionLogger
    //{
    //    static Logger Logger = LogManager.GetCurrentClassLogger();

    //    public static void LogWebServiceException(Exception e, IPrincipal principal)
    //    {

    //        var httpContext = MvcContext.GetContext();
    //        string exceptionDetails = FormatExceptionDetails(principal, httpContext, e,
    //            ErrorLocation.WebApi);

    //        Logger.Error(exceptionDetails);

    //    }

    //    public static void LogStorageException(Exception e, IPrincipal principal)
    //    {

    //        var httpContext = MvcContext.GetContext();
    //        string exceptionDetails = FormatExceptionDetails(principal, httpContext, e,
    //            ErrorLocation.Storage);

    //        Logger.Error(exceptionDetails);

    //    }

    //    ///// <summary>
    //    ///// Log an exception from the Web Site.
    //    ///// </summary>
    //    //public static void LogWebSiteException(Exception e, ICustomPrincipal principal)
    //    //{
    //    //    var httpContext = MvcContext.GetContext();

    //    //    string exceptionDetails = FormatExceptionDetails(principal, httpContext, e, ErrorLocation.WebSite);

    //    //    Logger.Error(exceptionDetails);
    //    //}

    //    ///// <summary>
    //    ///// Log an exception from the Client.
    //    ///// </summary>
    //    //public static void LogClientError(Exception e, ICustomPrincipal principal, Version clientVersion)
    //    //{
    //    //    string exceptionDetails = FormatExceptionDetails(principal, e, clientVersion);

    //    //    Logger.Error(exceptionDetails);
    //    //}

    //    /// <summary>
    //    /// Log an exception from the Windows Service or Console Application.
    //    /// </summary>
    //    public static void LogException(Exception e)
    //    {
    //        Logger.Error(FormatExceptionDetails(e));
    //    }

    //    #region Format Exception Email

    //    //private static string FormatExceptionDetails(ICustomPrincipal principal, Exception e, Version clientVersion)
    //    //{
    //    //    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    //    //    sb.AppendLine("Client Exception\n");

    //    ////    GetExceptionEmailUserInfo(sb, principal, clientVersion);

    //    ////    while (e != null)
    //    ////    {
    //    ////        sb.AppendLine("Exception:");
    //    ////        sb.AppendFormat("  Message: {0}\n", e.Message);
    //    ////        sb.AppendFormat("  Source:  {0}\n", e.Source);
    //    ////        sb.AppendFormat("  Stack Trace:\n{0}", e.StackTrace);

    //    ////        e = e.InnerException;
    //    ////        if (e != null)
    //    ////            sb.Append("\n\nInner ");
    //    ////    }

    //    ////    return sb.ToString();
    //    ////}

    //    //private static void GetExceptionEmailUserInfo(System.Text.StringBuilder sb, ICustomPrincipal principal, Version clientVersion)
    //    //{
    //    //    if (principal != null && principal.User != null)
    //    //    {
    //    //        // Print user information
    //    //        sb.AppendLine("User:");
    //    //        sb.AppendFormat("  Email:   {0}\n", principal.User.Email);
    //    //        sb.AppendFormat("  User ID: {0}\n", principal.User.Id);
    //    //        sb.AppendFormat("  Version: {0}\n\n", (clientVersion == null ? "Unknown" : clientVersion.ToString()));
    //    //    }
    //    }

    //private static string FormatExceptionDetails(IPrincipal principal,
    //    HttpContext httpContext, Exception e, ErrorLocation location)
    //{
    //    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    //    sb.AppendFormat("{0} Exception\n\n", location);

    //    if (httpContext != null)
    //    {
    //        HttpContext request = null;

    //        // TODO: Need a better way to determine if the request property is available other then try-catch
    //        try
    //        {
    //            request = httpContext;
    //        }
    //        catch (Exception) { }

    //        if (null != request)
    //        {
    //            sb.AppendLine("HTTP Request:");
    //            sb.AppendFormat("  URL:     {0}\n", httpContext.Request.Host);
    //            sb.AppendFormat("  Query:   {0}\n", httpContext.Request.QueryString);
    //            sb.AppendFormat("  Referer: {0}\n", httpContext.Request.PathBase);
    //            sb.AppendFormat("  Method:  {0}\n", httpContext.Request.PathBase);
    //            sb.AppendFormat("  IP Addr: {0}\n", GetClientIpAddress(httpContext.Request));
    //            sb.AppendFormat("  Server:  {0}\n\n","");
    //        }
    //        else
    //        {
    //            sb.AppendLine("HTTP Request is not available");
    //        }
    //    }

    //var customPrincipal = principal as ICustomPrincipal;

    //    if (customPrincipal != null && customPrincipal.User != null)
    //    {
    //        var user = customPrincipal.User;

    //        // Print user information
    //        sb.AppendLine("User:");
    //        sb.AppendFormat("  Email:   {0}\n", user.Email);
    //        sb.AppendFormat("  User ID: {0}\n", user.Id);

    //        sb.AppendLine();
    //    }

    //    // Print exception and inner exception info
    //    Exception innerException = e;
    //    while (innerException != null)
    //    {
    //        sb.AppendLine("Exception:");
    //        sb.AppendFormat("  Type:    {0}\n", innerException.GetType().FullName);
    //        sb.AppendFormat("  Message: {0}\n", innerException.Message);
    //        sb.AppendFormat("  Source:  {0}\n", innerException.Source);

    //        SqlException sqlException = innerException as SqlException;
    //        if (sqlException != null)
    //        {
    //            sb.AppendFormat("   Number:    {0}\n", sqlException.Number);
    //            sb.AppendFormat("   Line #:    {0}\n", sqlException.LineNumber);
    //            sb.AppendFormat("   Procedure: {0}\n", sqlException.Procedure);
    //            sb.AppendFormat("   Server:    {0}\n", sqlException.Server);
    //            sb.AppendFormat("   State:     {0}\n", sqlException.State);
    //            sb.AppendFormat("   Source:    {0}\n", sqlException.Source);
    //            sb.AppendLine();
    //        }

    //        if (innerException.Data.Keys.Count > 0)
    //        {
    //            sb.AppendLine("Exception Data:");

    //            foreach (object key in innerException.Data.Keys)
    //                sb.AppendFormat("  {0,10}: {1}\n", key, "   " + innerException.Data[key].ToString().Replace("\n", "\n   "));

    //            sb.AppendLine();
    //        }

    //        //HttpException httpException = innerException as HttpException;
    //        //if (httpException != null)
    //        //    sb.AppendFormat("   HTTP Code: {0}\n", httpException.GetHttpCode());

    //        //sb.AppendFormat("  Stack Trace: \n{0}", innerException.StackTrace);
    //        //innerException = innerException.InnerException;

    //        if (innerException != null)
    //            sb.Append("\n\nInner ");
    //    }

    //    return sb.ToString();
    //}

    //private static string FormatExceptionDetails(Exception e)
    //{
    //    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    //    sb.AppendLine("General Exception\n");

    //    while (e != null)
    //    {
    //        sb.AppendLine("Exception:");
    //        sb.AppendFormat("  Type:    {0}\n", e.GetType().FullName);
    //        sb.AppendFormat("  Message: {0}\n", e.Message);
    //        sb.AppendFormat("  Source:  {0}\n", e.Source);
    //        sb.AppendFormat("  Stack Trace:\n{0}\n", e.StackTrace);

    //        e = e.InnerException;
    //        if (e != null)
    //            sb.Append("\n\nInner ");
    //    }

    //    return sb.ToString();
    //}

    //#endregion

    //private static string GetClientIpAddress(HttpRequest request)
    //{
    //    // X-Forwarded-For is set by STunnel/HAProxy when it forwards the request thru the load balancer
    //    // If X-Forwarded-For is set, then ignore the UserHostAddress
    //    string forwardedFor = request.Headers["X-Forwarded-For"];

    //    if (!String.IsNullOrEmpty(forwardedFor))
    //    {
    //        int commaPos = forwardedFor.IndexOf(',');
    //        return (commaPos > 0 ? forwardedFor.Substring(0, commaPos) : forwardedFor);
    //    }
    //    else
    //        return request.Host.ToUriComponent();
}